﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SpellChecker;
using TVGuide.DataAccess.Repository;
using TVGuide.DataAccess.Common;
using System.Text.RegularExpressions;
using System.ComponentModel.DataAnnotations;
using TVGuide.Common;
using TVGuide.UI.HTMLHelpers;
using TVGuide.DataAccess;
using System.Data;


namespace TvGuide.UI.Models
{
    public class SearchData
    {
        public List<Program> AccardionProgramList = new List<Program>();
        public List<string> ShowResulsList = new List<string>();
        private DbAccessHelper access_helper = new DbAccessHelper();
        private SpCheckerModel searchEngine = new SpCheckerModel();
        private bool initialized = false;
        private List<String> inputList = new List<string>();
        private int lang;
        private CommonStr comm_str;
        private List<ProgCategory> CatList;

        public List<bool> testcat { get; set; }

        public List<string> partstr { get; set; }       

        public List<ProgCategory> Catlist
        {
            get { return this.CatList; }
        }

        public string SearchText { get; set; }
        public string StartDateText { get; set; }
        public string EndDateText { get; set; }
     //   public string SearchText_lbl { get; set; }
     //   public string StartDateText_lbl { get; set; }
      //  public string EndDateText_lbl { get; set; }

        public SearchData(int lang)
        {
            this.lang = lang;
            this.comm_str = new CommonStr(ResUtil.GetLang(this.lang));
            if (!initialized)
            {
                init();
                initialized = true;
            }
        }

        
        private void resetViewData()
        {
            this.partstr.Clear();
            AccardionProgramList.Clear();
        }


        public void SplitChar(string query)
        {
            this.partstr.Clear();
            if (query == null)
                return;
            char[] SPLIT = new char[] {' ','~','`','!','#','$','%','^','&','*','(',')','_','-','+','=','|','\\',',','<','>','.',
                                       '/','?','՝','~','{','}','[',']','«','»','՞','"','\''};
            string[] temp = query.Split(SPLIT);
            foreach (string ss in temp)
                if (ss.Length >= 2)
                    this.partstr.Add(ss);

        }

        private void CategoryInit(int lng)
        {
            //this.CatList = new List<ProgCategory>();
            //this.testcat = new List<bool>();
            //var cat = CategoryRepository.Instance().Get(o => o.Priority != null).OrderBy(o => o.Priority);
            //foreach (var category in cat)
            //{
            //    this.CatList.Add(new ProgCategory() { color = "#" + category.Color, CatId = category.Id, CatName = category.Name, CatDispName = setCatdispName(category.Id) });
            //    this.testcat.Add(false);
            //}

            this.CatList = new List<ProgCategory>();
            this.testcat = new List<bool>();
            int error_code;
            DataTable dt = access_helper.GetAllCategory(out error_code);
            if (error_code != 0)
                return;

            foreach (DataRow dr in dt.Rows)
            {
                this.CatList.Add(new ProgCategory() { color = "#" + Convert.ToString(Utils.ConvertDbNulls(dr["color"])), CatId = Convert.ToInt16(dr["catID"]), CatName = Convert.ToString(Utils.ConvertDbNulls(dr["catName"])), CatDispName = setCatdispName(Convert.ToInt16(dr["catID"])) });
                this.testcat.Add(false);
            }
            //var cat = CategoryRepository.Instance().Get(o=>o.Priority!=null).OrderBy(o=>o.Priority);
            //foreach (var category in cat)
            //    this.CatList.Add(new ProgCategory() { color = "#"+category.Color, CatId = category.Id, CatName = category.Name, CatDispName = setCatdispName(category.Id) });
        }



        private string setCatdispName(short id)
        {
            string name = "";
            switch (id)
            {
                case 1:
                    name = this.comm_str.NEWS_LBL;
                    break;
                case 2:
                    name = this.comm_str.FILMS_LBL;
                    break;
                case 3:
                    name = this.comm_str.MUSIC_LBL;
                    break;
                case 4:
                    name = this.comm_str.CHILDREN_LBL;
                    break;
                case 5:
                    name = this.comm_str.SPORT_LBL;
                    break;
                case 8:
                    name = this.comm_str.HUMOR_LBL;
                    break;

            }

            return name;

        }
     
       
        private void init()
        {  
            this.partstr = new List<string>();
            this.comm_str = new CommonStr(ResUtil.GetLang(this.lang));
            DateTime today = DateTime.Today.AddHours(Utils.ZoneHour);
            int error_code;
            DataTable dt = access_helper.GetAllProgramsWithSpecDate(out error_code, today.AddDays(-1), today.AddDays(20));
            if (error_code != 0)
                return;

            foreach (DataRow dr in dt.Rows)
            {
                inputList.Add(Convert.ToString(Utils.ConvertDbNulls(dr["title"])));
            }


            //var DataAcc = ProgramRepository.Instance();
           
            //var CurrList = DataAcc.Get(o => o.Date >= today.AddDays(-1)).ToList();
            //foreach (var item in CurrList)
            //{
            //    inputList.Add(item.Name);
            //}
            searchEngine.initSearchEngine(inputList);
            CategoryInit(this.lang);
        }

        public List<string> getAutocompleteList(string searchText)
        {
            int maxCount = 10;
            ShowResulsList.Clear();
            DateTime start = DateTime.Now.AddHours(Utils.ZoneHour);
            List<string> _resulsList = getSearchResults(searchText);
            DateTime end = DateTime.Now.AddHours(Utils.ZoneHour);
            long diff = end.Millisecond - start.Millisecond;          
            _resulsList = _resulsList.Distinct().ToList();
            ShowResulsList = _resulsList.Take(maxCount).ToList();
            _resulsList.Clear();
            return ShowResulsList;
        }

        public void searchSugesstedPrograms(string query)
        {
            var list = getSearchResults(query);
            List<Program> programlist = new List<Program>();
            int error_code;
            DataTable dt = access_helper.GetAllProgramsWithSpecDate(out error_code, DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1), DateTime.Now.AddDays(20));
            if (error_code != 0)
                return;


          //  var DataAcc = ProgramRepository.Instance();

          //  List<Program> programlist = new List<Program>();
            //var beggininglist = DataAcc.Get(o => o.Date >= DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1)).ToList();

            //if (list.Count > 0)
            //    foreach (var item in list)
            //    {
            //        foreach (var prg in beggininglist)
            //        {
            //                if (prg.Name.Trim().Contains(item))
            //                    programlist.Add(prg);
            //        }
            //    }

            if (list.Count > 0)
                foreach (var item in list)
                {
                    foreach (DataRow dr in dt.Rows)
                    {
                        if (Convert.ToString(Utils.ConvertDbNulls(dr["title"])).Trim().Contains(item))
                            programlist.Add(new Program() { CategoryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"])), ChannelId = Convert.ToInt32(Utils.ConvertDbNulls(dr["channelID"])), CountryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["countryID"])), Date = Convert.ToDateTime(Utils.ConvertDbNulls(dr["date"])), Description = Convert.ToString(Utils.ConvertDbNulls(dr["description"])), LanguageId = Convert.ToInt16(Utils.ConvertDbNulls(dr["languageID"])), Name = Convert.ToString(Utils.ConvertDbNulls(dr["title"])) });
                    }
                }

            AccardionProgramList.Clear();
            AccardionProgramList.AddRange(programlist);

            //foreach (var item in list)
            //{
            //    var a = DataAcc.Get(o => o.Date >= DateTime.Today.AddDays(-1) && o.Name.Contains(item)).ToList();
            //    SearchedProgramsList.Add(a);
            //}
           
        }

        internal void searchExactProgram(string query)
        {
            List<Program> programlist = new List<Program>();

            int error_code;
            DataTable dt = access_helper.GetAllProgramsWithSpecDate(out error_code, DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1), DateTime.Now.AddDays(20));
            if (error_code != 0)
                return;

          //  var beggininglist = DataAcc.Get(o => o.Date >= DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1)).ToList();
            //foreach (var prg in beggininglist)
            //{
            //    if (prg.Name.Trim().StartsWith(query))
            //        programlist.Add(prg);
            //}

            foreach (DataRow dr in dt.Rows)
            {
                if (Convert.ToString(Utils.ConvertDbNulls(dr["title"])).Trim().StartsWith(query))
                    programlist.Add(new Program() { CategoryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"])), ChannelId = Convert.ToInt32(Utils.ConvertDbNulls(dr["channelID"])), CountryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["countryID"])), Date = Convert.ToDateTime(Utils.ConvertDbNulls(dr["date"])), Description = Convert.ToString(Utils.ConvertDbNulls(dr["description"])), LanguageId = Convert.ToInt16(Utils.ConvertDbNulls(dr["languageID"])), Name = Convert.ToString(Utils.ConvertDbNulls(dr["title"])) });
            }


            AccardionProgramList.Clear();
            AccardionProgramList.AddRange(programlist);
            
            //var a = DataAcc.Get(o => o.Date >= DateTime.Today.AddDays(-1) && Regex.Replace(o.Name, "[\\ : \" / < >]", " ")
            //    .Trim() == query.Trim()).ToList();
            //var a = DataAcc.Get(o => o.Date >= DateTime.Today.AddDays(-1) && o.Name.Trim().StartsWith(query.Trim()) ).ToList();
            //SearchedProgramsList.Add(a);   
        }


        internal List<short> getCatArray(List<bool> cat)
        {
            List<short> containscat = new List<short>();
            if (cat[0])
                containscat.Add(2);
            if (cat[1])
                containscat.Add(1);
            if (cat[2])
                containscat.Add(3);
            if (cat[3])
                containscat.Add(4);
            if (cat[4])
                containscat.Add(5);
            if (cat[5])
                containscat.Add(8);
            return containscat;
        }

        internal void searchProgram(String searchText, DateTime startDate, DateTime endDate, short[] catArr)
        {
            resetViewData();
            
            if(startDate == null || endDate == null)
                return;
            if (String.IsNullOrEmpty(searchText) && catArr.Length == 0)
                return;
            SplitChar(searchText);
            bool textExists = true;
            if(String.IsNullOrEmpty(searchText))
                textExists = false;
            bool inAllCats = false;
            if (catArr.Count() == 0)
                inAllCats = true;
            List<String> list = null;
            if(textExists)
                list = getSearchResults(searchText);


            int error_code;
            DataTable dt = access_helper.GetAllProgramsWithSpecDate(out error_code, startDate, endDate);
            if (error_code != 0)
                return;

          //  var DataAcc = ProgramRepository.Instance();
            List<Program> programlist = new List<Program>();
         //   List<Program> progsList = DataAcc.Get(o => o.Date >= startDate && o.Date <= endDate).ToList();
            //foreach (var prg in progsList)
            //{
            //    if (!(inAllCats || (prg.CategoryId != null && catArr.Contains((short)prg.CategoryId))))
            //        continue;

            //    if (textExists)
            //    {
            //        foreach (var item in list)
            //        { 
            //            if(prg.Name.Trim().Contains(item))
            //                programlist.Add(prg);
            //        }
            //    }   
            //    else
            //        programlist.Add(prg);
            //}

            foreach (DataRow dr in dt.Rows)
            {
                if (!(inAllCats || (Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"])) != null && catArr.Contains(Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"]))))))
                    continue;

                if (textExists)
                {
                    foreach (var item in list)
                    {
                        if (Convert.ToString(Utils.ConvertDbNulls(dr["title"])).Trim().Contains(item))
                            programlist.Add(new Program() { CategoryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"])), ChannelId = Convert.ToInt32(Utils.ConvertDbNulls(dr["channelID"])), CountryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["countryID"])), Date = Convert.ToDateTime(Utils.ConvertDbNulls(dr["date"])), Description = Convert.ToString(Utils.ConvertDbNulls(dr["description"])), LanguageId = Convert.ToInt16(Utils.ConvertDbNulls(dr["languageID"])), Name = Convert.ToString(Utils.ConvertDbNulls(dr["title"])) });

                    }
                }
                else
                    programlist.Add(new Program() { CategoryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["categoryID"])), ChannelId = Convert.ToInt32(Utils.ConvertDbNulls(dr["channelID"])), CountryId = Convert.ToInt16(Utils.ConvertDbNulls(dr["countryID"])), Date = Convert.ToDateTime(Utils.ConvertDbNulls(dr["date"])), Description = Convert.ToString(Utils.ConvertDbNulls(dr["description"])), LanguageId = Convert.ToInt16(Utils.ConvertDbNulls(dr["languageID"])), Name = Convert.ToString(Utils.ConvertDbNulls(dr["title"])) });
            }

            AccardionProgramList.Clear();
            AccardionProgramList.AddRange(programlist);
        }


        internal void normalizeDates(String startDateSt, String endDateSt, out DateTime startDate, out DateTime endDate)
        {
            startDate = new DateTime();
            endDate = new DateTime();
            try
            {
                startDate = Utils.ConvertToHyAMDate(startDateSt);
                endDate = Utils.ConvertToHyAMDate(endDateSt);
            }
            catch (Exception) { }

            DateTime defaultDate = new DateTime();
            if (startDate.Equals(defaultDate))
            {
                if (endDate.Equals(defaultDate))
                {
                    startDate = DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1);
                    endDate = DateTime.Now.AddHours(Utils.ZoneHour).AddDays(7);
                }
                else
                {
                    startDate = endDate.AddDays(-7);
                }
            }
            if (endDate.Equals(defaultDate))
            {
                if (startDate.Equals(defaultDate))
                {
                    startDate = DateTime.Now.AddHours(Utils.ZoneHour).AddDays(-1);
                    endDate = DateTime.Now.AddHours(Utils.ZoneHour).AddDays(7);
                }
                else
                {
                    endDate = startDate.AddDays(7);
                }
            }
            endDate = endDate.AddHours(23).AddMinutes(59); // last hour/minute of a date
        }

        private static string FormatStrToDateTime(string date)
        {
            if(date !=null)
            {
                string[] arr = date.Split('.');
                if (arr.Length == 3)
                    return arr[1] + "/" + arr[0] + "/" + arr[2];
            }
            return null;
        }

        private List<string> getSearchResults(string query)
        {
            List<StringRow> result = searchEngine.find(query);
            List<string> foundItems = new List<string>();
            foreach (var item in result)
            {
                foundItems.Add(item.Value.Trim());
            }
            return foundItems.Distinct().ToList();
        }


    }
    
}